#!/bin/bash
#
# lib/watcher
# Functions to control the configuration and operation of the watcher services

# Dependencies:
#
# - ``functions`` file
# - ``SERVICE_{TENANT_NAME|PASSWORD}`` must be defined
# - ``DEST``, ``DATA_DIR``, ``STACK_USER`` must be defined

# ``stack.sh`` calls the entry points in this order:
#
# - is_watcher_enabled
# - install_watcher
# - configure_watcher
# - create_watcher_conf
# - init_watcher
# - start_watcher
# - stop_watcher
# - cleanup_watcher

# Save trace setting
_XTRACE_WATCHER=$(set +o | grep xtrace)
set +o xtrace


# Defaults
# --------

# Set up default directories
WATCHER_REPO=${WATCHER_REPO:-${GIT_BASE}/openstack/watcher.git}
WATCHER_BRANCH=${WATCHER_BRANCH:-master}
WATCHER_DIR=$DEST/watcher

GITREPO["python-watcherclient"]=${WATCHERCLIENT_REPO:-${GIT_BASE}/openstack/python-watcherclient.git}
GITBRANCH["python-watcherclient"]=${WATCHERCLIENT_BRANCH:-master}
GITDIR["python-watcherclient"]=$DEST/python-watcherclient

WATCHER_STATE_PATH=${WATCHER_STATE_PATH:=$DATA_DIR/watcher}
WATCHER_AUTH_CACHE_DIR=${WATCHER_AUTH_CACHE_DIR:-/var/cache/watcher}

WATCHER_CONF_DIR=/etc/watcher
WATCHER_CONF=$WATCHER_CONF_DIR/watcher.conf
WATCHER_POLICY_YAML=$WATCHER_CONF_DIR/policy.yaml.sample

WATCHER_DEVSTACK_DIR=$WATCHER_DIR/devstack
WATCHER_DEVSTACK_FILES_DIR=$WATCHER_DEVSTACK_DIR/files

if is_ssl_enabled_service "watcher" || is_service_enabled tls-proxy; then
    WATCHER_SERVICE_PROTOCOL="https"
fi

# Support entry points installation of console scripts
if [[ -d $WATCHER_DIR/bin ]]; then
    WATCHER_BIN_DIR=$WATCHER_DIR/bin
else
    WATCHER_BIN_DIR=$(get_python_exec_prefix)
fi

# There are 2 modes, which is "uwsgi" which runs with an apache
# proxy uwsgi in front of it, or "mod_wsgi", which runs in
# apache. mod_wsgi is deprecated, don't use it.
WATCHER_USE_WSGI_MODE=${WATCHER_USE_WSGI_MODE:-$WSGI_MODE}
WATCHER_UWSGI=$WATCHER_BIN_DIR/watcher-api-wsgi
WATCHER_UWSGI_CONF=$WATCHER_CONF_DIR/watcher-uwsgi.ini

if is_suse; then
    WATCHER_WSGI_DIR=${WATCHER_WSGI_DIR:-/srv/www/htdocs/watcher}
else
    WATCHER_WSGI_DIR=${WATCHER_WSGI_DIR:-/var/www/watcher}
fi
# Public facing bits
WATCHER_SERVICE_HOST=${WATCHER_SERVICE_HOST:-$SERVICE_HOST}
WATCHER_SERVICE_PORT=${WATCHER_SERVICE_PORT:-9322}
WATCHER_SERVICE_PORT_INT=${WATCHER_SERVICE_PORT_INT:-19322}
WATCHER_SERVICE_PROTOCOL=${WATCHER_SERVICE_PROTOCOL:-$SERVICE_PROTOCOL}

if [[ "$WATCHER_USE_WSGI_MODE" == "uwsgi" ]]; then
    WATCHER_API_URL="$WATCHER_SERVICE_PROTOCOL://$WATCHER_SERVICE_HOST/infra-optim"
else
    WATCHER_API_URL="$WATCHER_SERVICE_PROTOCOL://$WATCHER_SERVICE_HOST:$WATCHER_SERVICE_PORT"
fi

# Entry Points
# ------------

# Test if any watcher services are enabled
# is_watcher_enabled
function is_watcher_enabled {
    [[ ,${ENABLED_SERVICES} =~ ,"watcher-" ]] && return 0
    return 1
}

#_cleanup_watcher_apache_wsgi - Remove wsgi files,
#disable and remove apache vhost file
function _cleanup_watcher_apache_wsgi {
    sudo rm -rf $WATCHER_WSGI_DIR
    sudo rm -f $(apache_site_config_for watcher-api)
    restart_apache_server
}

# cleanup_watcher() - Remove residual data files, anything left over from previous
# runs that a clean run would need to clean up
function cleanup_watcher {
    sudo rm -rf $WATCHER_STATE_PATH $WATCHER_AUTH_CACHE_DIR
    if [[ "$WATCHER_USE_WSGI_MODE" == "uwsgi" ]]; then
        remove_uwsgi_config "$WATCHER_UWSGI_CONF" "$WATCHER_UWSGI"
    else
        _cleanup_watcher_apache_wsgi
    fi
}

# configure_watcher() - Set config files, create data dirs, etc
function configure_watcher {
    # Put config files in ``/etc/watcher`` for everyone to find
    sudo install -d -o $STACK_USER $WATCHER_CONF_DIR

    local project=watcher
    local project_uc
    project_uc=$(echo watcher|tr a-z A-Z)
    local conf_dir="${project_uc}_CONF_DIR"
    # eval conf dir to get the variable
    conf_dir="${!conf_dir}"
    local project_dir="${project_uc}_DIR"
    # eval project dir to get the variable
    project_dir="${!project_dir}"
    local sample_conf_dir="${project_dir}/etc/${project}"
    local sample_policy_dir="${project_dir}/etc/${project}/policy.d"
    local sample_policy_generator="${project_dir}/etc/${project}/oslo-policy-generator/watcher-policy-generator.conf"

    # first generate policy.yaml
    oslopolicy-sample-generator --config-file $sample_policy_generator
    # then optionally copy over policy.d
    if [[ -d $sample_policy_dir ]]; then
        cp -r $sample_policy_dir $conf_dir/policy.d
    fi

    # Rebuild the config file from scratch
    create_watcher_conf
}

# create_watcher_accounts() - Set up common required watcher accounts
#
# Project              User         Roles
# ------------------------------------------------------------------
# SERVICE_TENANT_NAME  watcher      service
function create_watcher_accounts {
    create_service_user "watcher" "admin"

    local watcher_service=$(get_or_create_service "watcher" \
        "infra-optim" "Watcher Infrastructure Optimization Service")
    get_or_create_endpoint $watcher_service \
        "$REGION_NAME" \
        "$WATCHER_API_URL"\
        "$WATCHER_API_URL"\
        "$WATCHER_API_URL"
}

# _config_watcher_apache_wsgi() - Set WSGI config files of watcher
function _config_watcher_apache_wsgi {
    local watcher_apache_conf
    if [[ "$WATCHER_USE_WSGI_MODE" == "mod_wsgi" ]]; then
        local service_port=$WATCHER_SERVICE_PORT
        if is_service_enabled tls-proxy; then
            service_port=$WATCHER_SERVICE_PORT_INT
            service_protocol="http"
        fi
        sudo mkdir -p $WATCHER_WSGI_DIR
        sudo cp $WATCHER_DIR/watcher/api/app.wsgi $WATCHER_WSGI_DIR/app.wsgi
        watcher_apache_conf=$(apache_site_config_for watcher-api)
        sudo cp $WATCHER_DEVSTACK_FILES_DIR/apache-watcher-api.template $watcher_apache_conf
        sudo sed -e "
            s|%WATCHER_SERVICE_PORT%|$service_port|g;
            s|%WATCHER_WSGI_DIR%|$WATCHER_WSGI_DIR|g;
            s|%USER%|$STACK_USER|g;
            s|%APIWORKERS%|$API_WORKERS|g;
            s|%APACHE_NAME%|$APACHE_NAME|g;
        " -i $watcher_apache_conf
        enable_apache_site watcher-api
   fi

}

# create_watcher_conf() - Create a new watcher.conf file
function create_watcher_conf {
    # (Re)create ``watcher.conf``
    rm -f $WATCHER_CONF

    iniset $WATCHER_CONF DEFAULT debug "$ENABLE_DEBUG_LOG_LEVEL"
    iniset $WATCHER_CONF DEFAULT control_exchange watcher

    iniset_rpc_backend watcher $WATCHER_CONF

    iniset $WATCHER_CONF database connection $(database_connection_url watcher)
    iniset $WATCHER_CONF api host "$(ipv6_unquote $WATCHER_SERVICE_HOST)"

    if is_service_enabled tls-proxy; then
        iniset $WATCHER_CONF api host "$(ipv6_unquote $WATCHER_SERVICE_HOST)"
        iniset $WATCHER_CONF api port "$WATCHER_SERVICE_PORT_INT"
        # iniset $WATCHER_CONF api enable_ssl_api "True"
    else
        if [[ "$WATCHER_USE_WSGI_MODE" == "mod_wsgi" ]]; then
            iniset $WATCHER_CONF api host "$(ipv6_unquote $WATCHER_SERVICE_HOST)"
            iniset $WATCHER_CONF api port "$WATCHER_SERVICE_PORT"
        fi
    fi

    iniset $WATCHER_CONF oslo_policy policy_file $WATCHER_POLICY_YAML

    iniset $WATCHER_CONF oslo_messaging_notifications driver "messagingv2"

    configure_auth_token_middleware $WATCHER_CONF watcher $WATCHER_AUTH_CACHE_DIR
    configure_auth_token_middleware $WATCHER_CONF watcher $WATCHER_AUTH_CACHE_DIR "watcher_clients_auth"

    if is_fedora || is_suse; then
        # watcher defaults to /usr/local/bin, but fedora and suse pip like to
        # install things in /usr/bin
        iniset $WATCHER_CONF DEFAULT bindir "/usr/bin"
    fi

    if [ -n "$WATCHER_STATE_PATH" ]; then
        iniset $WATCHER_CONF DEFAULT state_path "$WATCHER_STATE_PATH"
        iniset $WATCHER_CONF oslo_concurrency lock_path "$WATCHER_STATE_PATH"
    fi

    if [ "$SYSLOG" != "False" ]; then
        iniset $WATCHER_CONF DEFAULT use_syslog "True"
    fi

    # Format logging
    setup_logging $WATCHER_CONF

    #config apache files
    if [[ "$WATCHER_USE_WSGI_MODE" == "uwsgi" ]]; then
        write_uwsgi_config "$WATCHER_UWSGI_CONF" "$WATCHER_UWSGI" "/infra-optim"
    else
        _config_watcher_apache_wsgi
    fi
    # Register SSL certificates if provided
    if is_ssl_enabled_service watcher; then
        ensure_certificates WATCHER

        iniset $WATCHER_CONF DEFAULT ssl_cert_file "$WATCHER_SSL_CERT"
        iniset $WATCHER_CONF DEFAULT ssl_key_file "$WATCHER_SSL_KEY"

        iniset $WATCHER_CONF DEFAULT enabled_ssl_apis "$WATCHER_ENABLED_APIS"
    fi
}

# create_watcher_cache_dir() - Part of the init_watcher() process
function create_watcher_cache_dir {
    # Create cache dir
    sudo install -d -o $STACK_USER $WATCHER_AUTH_CACHE_DIR
    rm -rf $WATCHER_AUTH_CACHE_DIR/*
}

# init_watcher() - Initialize databases, etc.
function init_watcher {
    # clean up from previous (possibly aborted) runs
    # create required data files
    if is_service_enabled $DATABASE_BACKENDS && is_service_enabled watcher-api; then
        # (Re)create watcher database
        recreate_database watcher

        # Create watcher schema
        $WATCHER_BIN_DIR/watcher-db-manage --config-file $WATCHER_CONF upgrade
    fi
    create_watcher_cache_dir
}

# install_watcherclient() - Collect source and prepare
function install_watcherclient {
    if use_library_from_git "python-watcherclient"; then
        git_clone_by_name "python-watcherclient"
        setup_dev_lib "python-watcherclient"
    fi
}

# install_watcher() - Collect source and prepare
function install_watcher {
    git_clone $WATCHER_REPO $WATCHER_DIR $WATCHER_BRANCH
    setup_develop $WATCHER_DIR
    if [[ "$WATCHER_USE_WSGI_MODE" == "mod_wsgi" ]]; then
        install_apache_wsgi
    fi
}

# start_watcher_api() - Start the API process ahead of other things
function start_watcher_api {
    # Get right service port for testing

    local service_port=$WATCHER_SERVICE_PORT
    local service_protocol=$WATCHER_SERVICE_PROTOCOL
    local watcher_url
    if is_service_enabled tls-proxy; then
        service_port=$WATCHER_SERVICE_PORT_INT
        service_protocol="http"
    fi
    if [[ "$WATCHER_USE_WSGI_MODE" == "uwsgi" ]]; then
        run_process "watcher-api" "$WATCHER_BIN_DIR/uwsgi --ini $WATCHER_UWSGI_CONF"
        watcher_url=$service_protocol://$SERVICE_HOST/infra-optim
    else
        watcher_url=$service_protocol://$SERVICE_HOST:$service_port
        enable_apache_site watcher-api
        restart_apache_server
        # Start proxies if enabled
        if is_service_enabled tls-proxy; then
            start_tls_proxy watcher '*' $WATCHER_SERVICE_PORT $WATCHER_SERVICE_HOST $WATCHER_SERVICE_PORT_INT
        fi
    fi

    echo "Waiting for watcher-api to start..."
    if ! wait_for_service $SERVICE_TIMEOUT $watcher_url; then
        die $LINENO "watcher-api did not start"
    fi

}

# start_watcher() - Start running processes, including screen
function start_watcher {
    # ``run_process`` checks ``is_service_enabled``, it is not needed here
    start_watcher_api
    run_process watcher-decision-engine "$WATCHER_BIN_DIR/watcher-decision-engine --config-file $WATCHER_CONF"
    run_process watcher-applier "$WATCHER_BIN_DIR/watcher-applier --config-file $WATCHER_CONF"
}

# stop_watcher() - Stop running processes (non-screen)
function stop_watcher {
    if [[ "$WATCHER_USE_WSGI_MODE" == "uwsgi" ]]; then
        stop_process watcher-api
    else
        disable_apache_site watcher-api
        restart_apache_server
    fi
    for serv in watcher-decision-engine watcher-applier; do
        stop_process $serv
    done
}

# Restore xtrace
$_XTRACE_WATCHER

# Tell emacs to use shell-script-mode
## Local variables:
## mode: shell-script
## End:
